package com.tool;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * 介绍：
 *    Jdbc工具类
 ************************************************************************************************** 
 * 特点：
 *    ①该工具类中的所有方法都是静态方法,从而可直接通过类名调用
 *    ②私有化构造函数,既禁止该类在外部new出实例,也禁止该类被其它外部类继承
 **************************************************************************************************    
 * 作用：
 *    ①获取当前线程内的Connection对象,即获取当前线程携带的Connection对象
 *    ②关闭当前线程内的Connection对象,即关闭当前线程携带的Connection对象,并将其从当前线程内移除
 *    ③开启事务（新建一个Connection对象,并为其关闭自动提交模式,最后将其存入到当前线程内）
 *    ④提交事务
 *    ⑤回滚事务
 ************************************************************************************************** 
 * 涉及技术：
 *    ThreadLocal的使用（为当前线程设置要携带的数据、获取当前线程携带的数据、移除当前线程携带的数据）
 **************************************************************************************************    
 * 用到的第三方库：
 **************************************************************************************************        
 * 连接池：
 *    不涉及
 */
public class JdbcTool
{
	
	private static String driverClassName = PropertiesTool.get("driverClassName");
	private static String url = PropertiesTool.get("url");
	private static String user = PropertiesTool.get("user");
	private static String password = PropertiesTool.get("password");
	private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();  //该对象用于“管理（设置、获取、移除）”当前线程携带的“数据（Connection对象）”                                                                              
	
	
	private JdbcTool(){}  //私有化构造函数,既禁止该类在外部new出实例,也禁止该类被其它外部类继承
	
	
	
	/**
	 * 静态代码块,当该类被“类加载器”加载时执行
	 */
	static
	{
		try
		{
			Class.forName(driverClassName);
		}
		catch(ClassNotFoundException e)
		{
			throw new RuntimeException(e);
		}
	}
	
	
	
	
	
	/**
	 * 介绍：获取当前线程内的数据库链接对象
	 * 注意：此方法只能从当前线程内获取Connection对象,千万不能使用DriverManager来新建一个Connection对象并存入到当前线程内最后返回,主要是为了避免,获取到的是一个未开启事务的Connection对象
	 */
	public static Connection getConnection()
	{
		return threadLocal.get();  //获取当前线程内的Connection对象,即获取当前线程携带的Connection对象.习惯用语：获取与当前线程绑定在一起的Connection对象
	}
	
	
	
	
	
	/**
	 * 关闭当前线程内的数据库链接对象,并将其从当前线程内移除
	 */
	public static void closeConnection()
	{
		Connection connection = threadLocal.get();
		try
		{
			connection.close();
		}
		catch(SQLException e)
		{
			throw new RuntimeException(e);
		}
		finally
		{
			threadLocal.remove();  //移除当前线程内的Connection对象.习惯用语：将当前线程和Connection对象进行解绑
		}
	}
	
	
	
	
	
	/**
	 * 开启事务
	 */
	public static void startTrasation()
	{
		try
		{
			Connection connection = null;
			if(driverClassName.contains("mysql"))  //如果连接的是mysql数据库
			{
				connection = DriverManager.getConnection(url, user, password);
			}
			else
			{
				connection = DriverManager.getConnection(url);  //如果连接的是access数据库
			}
			connection.setAutoCommit(false);  //关闭Connection对象的自动提交模式
			threadLocal.set(connection);  //为当前线程设置要携带的Connection对象,即将Connection对象存入到当前线程内,那么只要“在当前线程执行范围内”通过threadLocal获取到的Connection对象必定是一个已经开启事务的对象
		}
		catch(SQLException e)
		{
			throw new RuntimeException(e);
		}
	}
	
	
	
	
	
	/**
	 * 提交事务
	 */
	public static void commitTrasation()
	{
		Connection connection = threadLocal.get();
		try
		{
			connection.commit();
		}
		catch(SQLException e)
		{
			throw new RuntimeException(e);
		}
	}
	
	
	
	
	
	/**
	 * 回滚事务
	 */
	public static void rollbackTrasation()
	{
		Connection connection = threadLocal.get();
		try
		{
			connection.rollback();
		}
		catch(SQLException e)
		{
			throw new RuntimeException(e);
		}
	}
	
	
	
}